#include "databuffer.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <memory>
#include "qdebug.h"


DataBuffer::DataBuffer()
{
    load();
    start();
}

DataBuffer::~DataBuffer() {}

DataBuffer &DataBuffer::instance()
{
    static std::shared_ptr<DataBuffer> s_instance( new DataBuffer() );
    static DataBuffer &                s_insteanc_ref = *s_instance;
    return s_insteanc_ref;
}

void DataBuffer::load()
{
    QFile file( "./data.json" );
    if ( !file.open( QIODevice::ReadWrite ) ) {
        return;
    }
    QJsonParseError error;
    QJsonDocument   jsDoc = QJsonDocument::fromJson( file.readAll(), &error );
    if ( error.error != QJsonParseError::NoError ) {
        qDebug() << error.errorString();
        return;
    }

    QJsonObject jsObj = jsDoc.object();
    if ( !jsObj.contains( "data" ) ) {
        return;
    }

    QJsonArray jsArr = jsObj["data"].toArray();
    for ( auto it = jsArr.begin(); it != jsArr.end(); ++it ) {
        QJsonObject obj = it->toObject();
        if ( !obj.contains( "id" ) || !obj.contains( "vaild" ) || !obj.contains( "key" ) || !obj.contains( "value" ) ) {
            continue;
        }
        _all_buffer_map.insert( obj["id"].toInt(), DataNode( obj["key"].toString(), obj["value"].toString(), obj["vaild"].toBool() ) );
    }
    file.close();
}

void DataBuffer::save()
{
    QFile file( "./data.json" );
    if ( !file.open( QIODevice::ReadWrite | QIODevice::Truncate ) ) {
        return;
    }
    QJsonArray   jsArr;
    QMutexLocker locker( &_mutex );
    for ( auto it = _all_buffer_map.begin(); it != _all_buffer_map.end(); ++it ) {
        jsArr.append( QJsonObject{ { "id", it.key() }, { "vaild", it->vaild }, { "key", it->key }, { "value", it->value } } );
    }
    file.write( QJsonDocument( QJsonObject{ { "data", jsArr } } ).toJson( QJsonDocument::Indented ) );
    file.close();
}


QMap<int, DataBuffer::DataNode> DataBuffer::getDataBuffer()
{
    QMutexLocker locker( &_mutex );
    return _all_buffer_map;
}

void DataBuffer::setDataVaild( const int &id, const bool vaild )
{
    QMutexLocker locker( &_mutex );
    if ( !_all_buffer_map.count( id ) ) {
        _all_buffer_map.insert( id, DataNode() );
    }
    _all_buffer_map[id].vaild = vaild;
}

void DataBuffer::setDataKey( const int &id, const QString &key )
{
    QMutexLocker locker( &_mutex );
    if ( !_all_buffer_map.count( id ) ) {
        _all_buffer_map.insert( id, DataNode() );
    }
    _all_buffer_map[id].key = key;
}

void DataBuffer::setDataValue( const int &id, const QString &value )
{
    QMutexLocker locker( &_mutex );
    if ( !_all_buffer_map.count( id ) ) {
        _all_buffer_map.insert( id, DataNode() );
    }
    _all_buffer_map[id].value = value;
}

bool DataBuffer::matchDataValue( const QByteArray &key, QByteArray &value )
{
    QMutexLocker locker( &_mutex );
    foreach ( auto it, _all_buffer_map ) {
        //        qDebug() << it.key_by.toHex( ' ' ) << key.toHex( ' ' );
        if ( !it.key_by.compare( key ) ) {
            if ( !it.vaild ) {
                return false;
            }
            if ( it.value_by.isEmpty() ) {
                return false;
            }
            value = it.value_by;
            return true;
        }
    }
    return false;
}

void DataBuffer::run()
{
    while ( !this->isInterruptionRequested() ) {
        save();
        QThread::sleep( 1 );
    }
}


QByteArray DataBuffer::stringToByteArray( const QString &str )
{
    QByteArray retVal;
    if ( str.contains( " " ) ) {
        QStringList strlist = str.toLower().split( " " );
        bool        ok;
        foreach ( QString s, strlist ) {
            qint8 byte = s.toInt( &ok, 16 );
            //                        qDebug( "%02X", byte );
            retVal.append( byte );
        }
    }
    else {
        retVal = str.toLatin1();
    }

    return retVal;
}
